#ifndef DRV_GM6020_H
#define DRV_GM6020_H

#include "fdcan.h"

#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"

/**
 * @brief GM6020电机的控制模式
 */
typedef enum
{
    GM_VOLTAGE_CONTROL = 0, // 电压控制
    GM_CURRENT_CONTROL = 2  // 电流控制
} GM6020Mode_t;

/**
 * @brief GM6020电机实例
 */
typedef struct
{
    /* 电机参数 */
    uint8_t motorID;      // 电机ID
    uint8_t motorIDGroup; // 电机ID所在的组
    GM6020Mode_t mode;    // 电机控制模式

    /* CAN通信相关 */
    FDCAN_HandleTypeDef *hfdcan; // CAN控制器的句柄
    uint32_t cmdStdID;           // 发送控制指令到CAN控制器的标识符
    uint8_t cmdBufRow;           // 控制指令缓冲区中, 电机实例对应的行号
    uint8_t cmdBufColHigh;       // 控制指令缓冲区中, 电机实例对应的指令高8位的列号
    uint8_t cmdBufColLow;        // 控制指令缓冲区中, 电机实例对应的指令低8位的列号

    /* 角度信息相关 */
    FunctionalState initFlag; // 初始化标志
    uint8_t initCnt;          // 用于初始化的计数器
    uint16_t lastAngle;       // 上次的机械角度
    int16_t overflowCnt;      // 机械角度溢出次数
} GM6020_t;

/**
 * @brief GM6020电机反馈信息的消息结构体
 */
typedef struct
{
    uint16_t angle;      // 机械角度
    int16_t speed;       // 转速, 单位为rpm
    int16_t torque;      // 实际转矩
    int16_t overflowCnt; // 溢出次数
} GM6020FeedbackMsg_t;

/**
 * @brief 初始化一个GM6020电机实例
 * @param motor: GM6020电机实例
 * @param id: 电机ID
 * @param mode: 电机控制模式
 * @param hfdcan: FDCAN控制器的句柄
 * @retval None
 */
void GM6020_Init(GM6020_t *motor, uint8_t id, GM6020Mode_t mode, FDCAN_HandleTypeDef *hfdcan);

/**
 * @brief 处理GM6020电机实例的控制指令
 * @param motor: GM6020电机实例
 * @param cmd: 控制指令值
 * @param mutex: 互斥锁
 * @retval None
 */
void GM6020_WriteCmdBuf(GM6020_t *motor, int16_t cmd, SemaphoreHandle_t mutex);

/**
 * @brief 此函数放置在ISR中, 更新GM6020电机实例的反馈信息
 * @param rxData: CAN接收的缓存数组
 * @param motor: GM6020电机实例
 * @param motorInfoBoxHandle: 存放电机反馈信息的邮箱句柄
 * @retval None
 */
void ISR_GM6020_UpdateInfo(uint8_t rxData[], GM6020_t *motor, QueueHandle_t motorInfoBoxHandle);

/**
 * @brief 获取GM6020的编码器计数
 * @param feedbackBoxHandle: 存放电机反馈信息的邮箱句柄
 * @return GM6020的编码器计数
 */
int32_t GM6020_GetCnt(QueueHandle_t feedbackBoxHandle);

/**
 * @brief 获取GM6020的位置, 单位为度
 * @param feedbackBoxHandle: 存放电机反馈信息的邮箱句柄
 * @param baseCnt: 基准的编码器计数
 * @return GM6020的位置
 */
float GM6020_GetPos(QueueHandle_t feedbackBoxHandle, int32_t baseCnt);

/**
 * @brief 获取GM6020的转速, 单位为rpm
 * @param feedbackBoxHandle: 存放电机反馈信息的邮箱句柄
 * @return GM6020的转速
 */
float GM6020_GetRpm(QueueHandle_t feedbackBoxHandle);

#endif //DRV_GM6020_H
